﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using Ue.Framework.Collections;

namespace Ue.Qcdz.Domain.TreeViews
{
    public class TreeNode : Ue.Infrastructure.DomainBase.EntityBase
    {
        public TreeNode(TreeView treeView,ITreeNodeTag tag)
            : this(null,treeView, null,tag) { }

        public TreeNode(TreeView treeView, TreeNode parentNode, ITreeNodeTag tag)
            : this(null, treeView, parentNode, tag) { }

        public TreeNode(object key, TreeView treeView, TreeNode parentNode, ITreeNodeTag tag)
            : base(key)
        {
            this.TreeView = treeView;
            this.Parent = parentNode;
            this.Tag = tag;
        }

        public TreeView TreeView { get; protected set; }

        public virtual TreeNode Parent { get; protected set; }

        public int DisplayOrder { get; protected set; }

        public virtual IEnumerable<TreeNode> ChildNodes
        {
            get
            {
                return this.TreeView.Items.Where(item =>
                    {
                        return item != null
                            && item.Parent != null
                            && item.Parent.Equals(this);
                    }).OrderBy(item => item.DisplayOrder).ToList();
            }
        }

        internal void SetDisplayOrder()
        {
            if (this.DisplayOrder != 0)
            {
                return;
            }

            this.DisplayOrder = this.SiblingNodes.Contains(this)
                ? this.SiblingNodes.Count()
                : this.SiblingNodes.Count() + 1;
        }

        public void ChangeDisplayOrder(int newDisplayOrder)
        {
            if (newDisplayOrder <= 0)
            {
                newDisplayOrder = 1;
            }

            if (newDisplayOrder > this.SiblingNodes.Count())
            {
                newDisplayOrder = newDisplayOrder = this.SiblingNodes.Count();
            }

            if (this.DisplayOrder == newDisplayOrder)
            {
                return;
            }

            int min, max, step;
            if (newDisplayOrder > this.DisplayOrder)
            {
                step = -1;
                min = this.DisplayOrder;
                max = newDisplayOrder;
            }
            else
            {
                step = 1;
                min = newDisplayOrder;
                max = this.DisplayOrder;
            }

            IList<TreeNode> changeNodes = this.SiblingNodes.Where(item => item.DisplayOrder >= min && item.DisplayOrder <= max).ToList();

            changeNodes.Foreach(item =>
            {
                item.DisplayOrder += step;

                this.TreeView.Update(item);
            });

            this.DisplayOrder = newDisplayOrder;

            this.TreeView.Update(this);
        }

        public ITreeNodeTag Tag { get; protected set; }

        private IEnumerable<TreeNode> SiblingNodes
        {
            get
            {
                return this.Parent == null
                    ? this.TreeView.ChildNodes
                    : this.Parent.ChildNodes;
            }
        }
    }
}
